﻿// BTPDA.cpp : Defines the entry point for the application.
//
// ======================================================================================
//										HEADERS
// ======================================================================================
#include "stdafx.h"
#include "BTPDA.h"

#define MAX_LOADSTRING 100
// ======================================================================================
//										DECLARATIONS
// ======================================================================================
// Forward declarations of functions included in this code module:
ATOM			MyRegisterClass(HINSTANCE, LPTSTR);
BOOL			InitInstance(HINSTANCE, int);
BOOL WINAPI	MainDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL WINAPI	ControlDialogManager(HWND, UINT, WPARAM, LPARAM);

// ======================================================================================
//										GLOBAL VARS
// ======================================================================================

/// \brief handle global al aplicaţiei
HINSTANCE			g_hInst;
/// \brief menu bar handle
HWND				g_hWndMenuBar;		
/// \brief comanda pe care o transmit (V_UP, V_DOWN..)
BYTE				g_command[4];			

/// \brief Implementarea Microsoft a BluetoothStack
MicrosoftInterface microsoftBT;

/// \brief Current Bluetooth Stack
BluetoothStack& currentBT = microsoftBT;

/// \brief Index în vectorul \ref Devices al echipamentului la care gazda este conectată
int currentDevice;

POINT	startMousePosition;
POINT	endMousePosition;
BOOL	isDraggingOnPad;
BOOL	isStartingToDrag;
// ======================================================================================
/// \brief Listează echipamentele găsite în raza de acţiune a BT, folosind informaţiile din 
/// vectorul \ref Devices
// ======================================================================================
void DisplayDevices(HWND hDlg)
{
	WCHAR wbuf[NAME_LENGTH];
	HWND deviceList = GetDlgItem(hDlg, IDC_DEVLIST);
	// ===== Clear list contents
	SendMessage(deviceList, LB_RESETCONTENT, 0, 0);
	// Populate with found devices
	for(int i = 0 ; i < currentBT.foundDevicesCount; i++)
	{
		wcscpy( wbuf ,  currentBT.Devices[i].Name);
		if( currentBT.Devices[i].IsPaired == TRUE )
		{
			wcscat( wbuf, _T(" -- CONNECTED"));
		}
		// ===== Add the device to the list
		SendMessage(deviceList, LB_ADDSTRING, 0, (LPARAM) wbuf );
	}
	if( currentBT.foundDevicesCount <= 0 )
	{
		SendMessage(GetDlgItem(hDlg, IDC_DEVLIST),
				LB_ADDSTRING,
				0,
				(LPARAM) _T("Press \'Search\'")); 
	}
}
// ======================================================================================
// Main
// ======================================================================================
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
	g_hInst = hInstance;
	currentDevice = -1;
	
	// If any other impplementations in the future...
	currentBT = microsoftBT;
	if (currentBT.InitBluetooth() == OK)
	{
		DialogBox(hInstance, MAKEINTRESOURCE(IDD_VOLUME), NULL, ControlDialogManager);
	}
	else
	{
		MessageBox(NULL, _T("Could not initialize bluetooth!"), _T("Fatal Error"), MB_OK);
	}
	
	return 0;
}
// ======================================================================================
/// \brief Handler pentru mesajele primite în fereastra principală. Aici sunt tratate
/// butoanele multimedia şi padul pentru mouse
// ======================================================================================
BOOL WINAPI	ControlDialogManager(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    static SHACTIVATEINFO s_sai;
	
    switch (message) 
    {
        
	case WM_INITDIALOG:
			isDraggingOnPad = false;
            break;
	// Când ridic degetul de pe ecran, resetez orice acţiune începută anterior i.e. să urmăresc traseul mouseului
	case WM_LBUTTONUP:
			isDraggingOnPad = false;
			isStartingToDrag = false;
			break;
	// De fiecare dată când primesc mesajul de mişcare al mouseului, verific dacă este pe suprafaţa padului şi trimit
	// în consecinţă dx şi dy către PC, pentru a muta cursorul
	case WM_MOUSEMOVE:
		if( isDraggingOnPad == true && isStartingToDrag == false )
		{
			startMousePosition.x = LOWORD(lParam);
			startMousePosition.y = HIWORD(lParam);
			isStartingToDrag = true;
		}
		else if( isDraggingOnPad == true && isStartingToDrag == true)
		{
			endMousePosition.x = LOWORD(lParam);
			endMousePosition.y = HIWORD(lParam);

			g_command[0] = MOUSE_MOVE;
			g_command[1] = startMousePosition.x - endMousePosition.x;
			g_command[2] = startMousePosition.y - endMousePosition.y;
			currentBT.Send( g_command, 3 );

			startMousePosition.x = endMousePosition.x;
			startMousePosition.y = endMousePosition.y;
		}
	break;
	// Tratarea butoanelor
	case WM_COMMAND:
            wmId    = LOWORD(wParam); 
            wmEvent = HIWORD(wParam); 
            // Parse the menu selections:
            switch (wmId)
            {
			case BUTTON_BROWSE:
				DialogBox(g_hInst, MAKEINTRESOURCE(IDD_SEARCH), NULL, MainDlgProc);
				break;
			case BUTTON_VOLUME_UP:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_VOLUME_UP;
				currentBT.Send( g_command , 2 );
				break;
			case BUTTON_VOLUME_DOWN:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_VOLUME_DOWN;
				currentBT.Send( g_command , 2 );
				break;
			case BUTTON_VOLUME_MUTE:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_VOLUME_MUTE;
				currentBT.Send( g_command , 2 );
				break;
			case BUTTON_TRACK_NEXT:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_MEDIA_NEXT_TRACK;
				currentBT.Send( g_command , 2 );
				break;
			case BUTTON_TRACK_PREV:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_MEDIA_PREV_TRACK;
				currentBT.Send( g_command , 2 );
				break;
			case BUTTON_TRACK_PLAY_PAUSE:
				g_command[0] = KEY_INPUT;
				g_command[1] = VK_MEDIA_PLAY_PAUSE;
				currentBT.Send( g_command , 2 );
				break;
			case IDC_TOUCH_PAD:
				isDraggingOnPad = true;
				isStartingToDrag = false;
				break;
			case IDC_LEFT:
				g_command[0] = MOUSE_CLICK;
				currentBT.Send( g_command , 1 );
				break;
			case IDC_RIGTH:
				g_command[0] = MOUSE_RIGHT;
				currentBT.Send( g_command , 1 );
				break;
			break;
            }
			
            break;
			case WM_PAINT:
				hdc = BeginPaint(hDlg, &ps);
	            
				// TODO: Add any drawing code here...
	            
				EndPaint(hDlg, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        case WM_ACTIVATE:
            // Notify shell of our activate message
            SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
            break;
        case WM_SETTINGCHANGE:
            SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
            break;
		case WM_SIZE:
			
			break;
        default:
            return DefWindowProc(hDlg, message, wParam, lParam);
    }
    return 0;
}

// ======================================================================================
/// \brief Handler pentru mesajele primite în fereastra de căutare a echipamentelor din 
/// raza BT.
// ======================================================================================
BOOL WINAPI	MainDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    static SHACTIVATEINFO s_sai;
	
    switch (message) 
    {
        
	case WM_INITDIALOG:

            SHINITDLGINFO sid;
			sid.dwMask   = SHIDIM_FLAGS;
			sid.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
			sid.hDlg   = hDlg;
			// size dialog to full screen
			SHInitDialog(&sid);
			DisplayDevices(hDlg);
            break;	
	case WM_COMMAND:
            wmId    = LOWORD(wParam); 
            wmEvent = HIWORD(wParam); 
            // Parse the menu selections:
            switch (wmId)
            {
			case IDOK:
				EndDialog(hDlg, IDOK);
				break;
			case BUTTON_SEARCH:
				currentBT.SearchDevices();
				DisplayDevices(hDlg);
				
                break;
			case IDC_DEVLIST:
				HWND deviceList = GetDlgItem(hDlg, IDC_DEVLIST);

				switch( HIWORD(wParam) )
				{
				case LBN_DBLCLK:
					currentDevice = (UINT8) SendMessage( deviceList, LB_GETCURSEL, 0, 0);
					if( currentDevice >= currentBT.foundDevicesCount && currentDevice >= 0 )
					{
						break;
					}
					if( currentBT.Devices[currentDevice].IsPaired == FALSE )
					{
						if( currentBT.Connect( currentDevice ) == OK )
						{
							currentBT.Devices[currentDevice].IsPaired = true;
						}
					}
					else
					{
						currentBT.Disconnect( currentDevice );
						currentBT.Devices[currentDevice].IsPaired = false;
						currentDevice = -1;
					}
					DisplayDevices( hDlg );
					break;
				
				}
				break;

            }
			
            break;
			case WM_PAINT:
				hdc = BeginPaint(hDlg, &ps);
	            
				// TODO: Add any drawing code here...
	            
				EndPaint(hDlg, &ps);
            break;
        case WM_DESTROY:
			CloseHandle( hDlg );
            break;

        case WM_ACTIVATE:
            // Notify shell of our activate message
            SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
            break;
        case WM_SETTINGCHANGE:
            SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
            break;
		case WM_SIZE:
			CScreenLib::DockControl(hDlg , IDC_DEVLIST, CScreenLib::dtTop);
			CScreenLib::DockControl(hDlg , BUTTON_SEARCH, CScreenLib::dtBottom );
			
			CScreenLib::OptimizeWidth(hDlg, 2, BUTTON_SEARCH, IDC_DEVLIST);
			CScreenLib::OptimizeHeight(hDlg, IDC_DEVLIST);
			
			CScreenLib::AlignControls(hDlg, CScreenLib::atBottom, 1, BUTTON_SEARCH, IDC_DEVLIST);
			break;
        default:
            return DefWindowProc(hDlg, message, wParam, lParam);
    }
    return 0;
}
